#ifndef MY_RENDER_MATRIX
#define MY_RENDER_MATRIX
#include "./dot.hpp"
#include "./vector4.hpp"
#include <iostream>
using std::cout;
using std::endl;

class Matrix44{
    private:
    float** matrix;

    // 因为不好调试，所以需要有这些内容
    float x0y0;
    float x0y1;
    float x0y2;
    float x0y3;
    float x1y0;
    float x1y1;
    float x1y2;
    float x1y3;
    float x2y0;
    float x2y1;
    float x2y2;
    float x2y3;
    float x3y0;
    float x3y1;
    float x3y2;
    float x3y3;

    void insertValue(){
        x0y0=matrix[0][0];
        x0y1=matrix[0][1];
        x0y2=matrix[0][2];
        x0y3=matrix[0][3];
        x1y0=matrix[1][0];
        x1y1=matrix[1][1];
        x1y2=matrix[1][2];
        x1y3=matrix[1][3];
        x2y0=matrix[2][0];
        x2y1=matrix[2][1];
        x2y2=matrix[2][2];
        x2y3=matrix[2][3];
        x3y0=matrix[3][0];
        x3y1=matrix[3][1];
        x3y2=matrix[3][2];
        x3y3=matrix[3][3];
    }
    
    public:
    void printMatrix(){
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                std::cout<<matrix[i][j]<<" ";
            }
            std::cout<<std::endl;
        }
    }
    // 默认构造函数，初始化一个单位矩阵
    Matrix44() {
        matrix = new float*[4];
        for (int i = 0; i < 4; i++) {
            matrix[i] = new float[4];
            for (int j = 0; j < 4; j++) {
                matrix[i][j] = (i == j) ? 1.0f : 0.0f;
            }
        }
        insertValue();
    }
    // 根据一个一维数组生成一个4*4的矩阵
    Matrix44(float value[16]){
        matrix=new float*[4];
        matrix[0]=new float[4];
        matrix[1]=new float[4];
        matrix[2]=new float[4];
        matrix[3]=new float[4];
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                matrix[i][j]=value[i*4+j];
            }
        }
        insertValue();
    }
    Matrix44(float x0y0,float x0y1,float x0y2,float x0y3,float x1y0,float x1y1,float x1y2,float x1y3,float x2y0,float x2y1,float x2y2,float x2y3,float x3y0,float x3y1,float x3y2,float x3y3){
        matrix=new float*[4];
        matrix[0]=new float[4]{x0y0,x0y1,x0y2,x0y3};
        matrix[1]=new float[4]{x1y0,x1y1,x1y2,x1y3};
        matrix[2]=new float[4]{x2y0,x2y1,x2y2,x2y3};
        matrix[3]=new float[4]{x3y0,x3y1,x3y2,x3y3};
        insertValue();
    }
    Matrix44(const Matrix44& other) {
        matrix = new float*[4];
        for (int i = 0; i < 4; i++) {
            matrix[i] = new float[4];
            for (int j = 0; j < 4; j++) {
                matrix[i][j] = other.matrix[i][j];
            }
        }
        insertValue();
    }
    ~Matrix44(){
        if (matrix != nullptr) {
            for (int i = 0; i < 4; ++i) {
                delete[] matrix[i];
            }
            delete[] matrix;
            matrix = nullptr;
        }
    }

    Matrix44 operator+(const Matrix44& other) const {
        Matrix44 result;
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                result.matrix[i][j] = matrix[i][j] + other.matrix[i][j];
            }
        }
        result.insertValue();
        return result;
    }

    Matrix44 operator*(const Matrix44& other) const {
        Matrix44 result;
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                result.matrix[i][j] = 0; // 初始化result矩阵的元素为0
                for (int k = 0; k < 4; k++) {
                    result.matrix[i][j] += matrix[i][k] * other.matrix[k][j];
                }
            }
        }
        result.insertValue();
        return result;
    }

    Vector4 operator*(const Vector4& other) const {
        Vector4 result;
        result.x=matrix[0][0]*other.x+matrix[0][1]*other.y+matrix[0][2]*other.z+matrix[0][3]*other.w;
        result.y=matrix[1][0]*other.x+matrix[1][1]*other.y+matrix[1][2]*other.z+matrix[1][3]*other.w;
        result.z=matrix[2][0]*other.x+matrix[2][1]*other.y+matrix[2][2]*other.z+matrix[2][3]*other.w;
        result.w=matrix[3][0]*other.x+matrix[3][1]*other.y+matrix[3][2]*other.z+matrix[3][3]*other.w;
        return result;
    }

    Dot operator*(const Dot& other)const{
        float x=matrix[0][0]*other.x+matrix[0][1]*other.y+matrix[0][2]*other.z+matrix[0][3]*other.w;
        float y=matrix[1][0]*other.x+matrix[1][1]*other.y+matrix[1][2]*other.z+matrix[1][3]*other.w;
        float z=matrix[2][0]*other.x+matrix[2][1]*other.y+matrix[2][2]*other.z+matrix[2][3]*other.w;
        float w=matrix[3][0]*other.x+matrix[3][1]*other.y+matrix[3][2]*other.z+matrix[3][3]*other.w;
        if (w==1)
        return Dot(x,y,z,w);
        else{
            return Dot(x/w,y/w,z/w,1);
        }
    }

    Matrix44& operator=(const Matrix44& other) {
        if (this != &other) {
            // 清除当前的内存
            for (int i = 0; i < 4; ++i) {
                delete[] matrix[i];
            }
            delete[] matrix;
    
            matrix = new float*[4];
            for (int i = 0; i < 4; i++) {
                matrix[i] = new float[4];
                for (int j = 0; j < 4; j++) {
                    matrix[i][j] = other.matrix[i][j];
                }
            }
            insertValue();
        }
        return *this;
    }

    void set(int i,int j,float value){
        matrix[i][j]=value;
        insertValue();
    }

    float get(int i,int j){
        return matrix[i][j];
    }
};

#endif